Skip to content

Enable budget calculation for more than two phases#4264

Merged
koopmant merged 3 commits into
mainfrom
enable-more-phases-for-budget
Feb 11, 2026
Merged

Enable budget calculation for more than two phases#4264
koopmant merged 3 commits into
mainfrom
enable-more-phases-for-budget

Conversation

@koopmant
Copy link
Copy Markdown
Contributor

@koopmant koopmant commented Aug 20, 2025

New fields have been added to the ChallengeRequest model to define any number of phases for any number of tasks for the budget calculation.

The ChallengeRequestBudgetUpdateForm has been updated to allow changing these new fields. The new fields are initially filled with values from the old fields that are used by the ChallengeRequestCreateForm, which has not changed from the users perspective.

Because the challenge request can now define multiple tasks, runtime limits are set for the phases by supplying the corresponding task when they are converted to algorithm phases; unless there is only one task defined on the challenge request, then the input is not needed.

Screenshot 2025-09-16 at 20 54 19

Related to https://github.com/DIAGNijmegen/rse-roadmap/issues/421
Related to #3787

@koopmant koopmant force-pushed the enable-more-phases-for-budget branch from 3158b4a to 66ec801 Compare September 16, 2025 18:31
Comment thread app/grandchallenge/evaluation/forms.py
@koopmant koopmant marked this pull request as ready for review September 16, 2025 21:45
Comment thread app/grandchallenge/challenges/migrations/0060_auto_20250820_1420.py
@koopmant koopmant requested a review from jmsmkn September 18, 2025 07:45
Comment thread app/grandchallenge/evaluation/views/__init__.py Outdated
Comment thread app/grandchallenge/core/templatetags/index.py Outdated
Comment thread app/grandchallenge/challenges/templates/challenges/partials/budget_table.html Outdated
Comment thread app/grandchallenge/challenges/templatetags/budget.py Outdated
Comment thread app/grandchallenge/challenges/forms.py Outdated
Comment thread app/grandchallenge/challenges/models.py Outdated
@koopmant koopmant requested a review from jmsmkn October 23, 2025 08:08
@koopmant
Copy link
Copy Markdown
Contributor Author

@jmsmkn I don't think it is worth splitting up the PR or creating stacked commits, but let me know if this is annoying to review.

@jmsmkn
Copy link
Copy Markdown
Member

jmsmkn commented Oct 23, 2025

+1800 LOC is going to be too much for me to review this afternoon, sorry.

@koopmant
Copy link
Copy Markdown
Contributor Author

No worries, let me see if I can present this in chunks

@koopmant koopmant force-pushed the enable-more-phases-for-budget branch from 0e01495 to 937157b Compare October 23, 2025 15:46
@koopmant
Copy link
Copy Markdown
Contributor Author

Cleaned it into 6 commits. Fixed some issues along the way, so it's good that you did not review it before.

Should be ready now!

@chrisvanrun
Copy link
Copy Markdown
Member

Sorry! Heavy conflict with #4495. We'll need to discuss how to combine this and what makes more sense to merge first.

@koopmant koopmant closed this Jan 9, 2026
@koopmant koopmant force-pushed the enable-more-phases-for-budget branch from 1cc6a8c to 108509e Compare January 9, 2026 11:22
@koopmant
Copy link
Copy Markdown
Contributor Author

koopmant commented Jan 9, 2026

Ah, this get's automatically closed when the branch is up-to-date with main. I wanted to use this as a base for a feature branch with stacked PR's. Will open it again after the first PR.

@koopmant
Copy link
Copy Markdown
Contributor Author

@chrisvanrun I'm replying to your comment here, as this will be the final PR.

I suggest we use this PR to discuss the details.

The tasks were originally meant as a quick-n-dirty multiplier. In addition, the phase-setup form is mostly a time-saving construct for us not to have to input all those values manually.

I think making some of the fields multi-dimensional (i.e. creating an array of those values) might be a quick pattern that will work in the short term but will likely bite us in the future.

Writing out-loud here: what if we create a ChallengeRequestPhase object, with all the typical per-phase configurable fields (i.e. runtime, maximum settings, et cetera) and we include some estimation parameters. That would best match what it is meant to model: the predicted run through of a single Phase. It would automatically capture tasks and could be used for all kind of future improvements. Setting up a Phase would involve selecting one of the ChallengeRequestPhase to set it up.

How do you think this will bite us in the future?

I don't follow how adding a new ChallengeRequestPhase model is going to automatically capture tasks. A task can have multiple phases and the budget depends on which task a phase is a part of, mainly because submissions to phases of the same tasks should not be counted separately, since a submissions to the final phase should already be submitted to earlier phases. I'd expect a ChallengeRequestTask would be necessary in that case. But either way, it would be way more complicated than this. I remember talking with James about adding a Task model and we agreed we shouldn't add models unless we absolutely have to. I don't think that is the case here.

@chrisvanrun
Copy link
Copy Markdown
Member

I don't follow how adding a new ChallengeRequestPhase model is going to automatically capture tasks. A task can have multiple phases and the budget depends on which task a phase is a part of, mainly because submissions to phases of the same tasks should not be counted separately, since a submissions to the final phase should already be submitted to earlier phases.

In the idea that tasks are a 'simple' combination of phases. However, I had not taken into consideration that tasks are also unifying some costs related with submissions. That makes the modelling quite a bit more difficult!

In the future, we might want to add additional properties which might be easier added when modelled instead of increasing dimensionality in some of the fields. But I'd have to have a closer look at how the dimensionality is handled in your changes.

@chrisvanrun
Copy link
Copy Markdown
Member

chrisvanrun commented Jan 19, 2026

A quick study has me sketch your implementation as follows, please let me know if it is not correct.

Per Task

  • inference_time_average_minutes_for_tasks - Average run time per algorithm job in minutes, for each task
  • algorithm_selectable_gpu_type_choices_for_tasks - GPU type choices for algorithm inference jobs, for each task
  • algorithm_maximum_settable_memory_gb_for_tasks - Maximum settable memory in GB, for each task
  • average_size_test_case_mb_for_tasks - Average size of test image in MB, for each task

Per Phase

  • number_of_teams_for_phases - Number of teams for each phase
  • number_of_submissions_per_team_for_phases - Number of submissions per team for each phase
  • number_of_test_cases_for_phases - Number of test images for each phase
  • task_id_for_phases - Indicates which phase belongs to which task

Other

  • task_ids - List of task IDs (not per-task or per-phase, but defines the tasks themselves)

We keep the main relationship between task and phases via task_id_for_phases. I like how we have everything in a single query. I do worry about maintainability and data integrity. Adding another field or relation becomes a bit of a hassle, which we'd get more easily done using Django ORM. However, I don't think we'll be adding a relation, since phases and tasks are sort of at the core of the challenge setup. Data integrity goes via array indexing and isn't currently checked. At the other hand, I don't think we have sufficient appetite to make this a model architecture: given the work already poured into this.

Hence, I suggest tackling the integrity and check the fields on the model:

  • ensuring the tasks indices exist when referenced from task_id_for_phases
  • ensuring equal length of each of these fields in the per-phase and per-task scope

@koopmant
Copy link
Copy Markdown
Contributor Author

A quick study has me sketch your implementation as follows, please let me know if it is not correct.

That is all correct.

ensuring the tasks indices exist when referenced from task_id_for_phases
ensuring equal length of each of these fields in the per-phase and per-task scope

I believe I have these covered in the ChallengeRequestBudgetUpdateForm. In particular in _clean_task_id_for_phases, _clean_task_lists_equal_length, and self._clean_phases_lists_equal_length.

@chrisvanrun
Copy link
Copy Markdown
Member

I believe I have these covered in the ChallengeRequestBudgetUpdateForm. In particular in _clean_task_id_for_phases, _clean_task_lists_equal_length, and self._clean_phases_lists_equal_length.

Ah, darn. Sorry! I used a reference lookup on the model.field, but that of course doesn't hit the form. Silly me.

One classic argument is moving those to the model so we don't end-up with integrity problems if we edit via the backend. Relevant, since we are maybe planning on removing the budget fields from the requests. However, I think we'll likely want to work on this via the frontend form anyway, even if we remove those. So then the argument is mute. Do you agree?

@koopmant
Copy link
Copy Markdown
Contributor Author

Yes, the budget update form is for us to change it through the frontend. I think it is fine to keep the validation there.

@koopmant koopmant reopened this Jan 20, 2026
@chrisvanrun
Copy link
Copy Markdown
Member

It is alive again!

@koopmant koopmant force-pushed the enable-more-phases-for-budget branch from 1331e8d to ddc86a1 Compare February 10, 2026 15:07
@chrisvanrun
Copy link
Copy Markdown
Member

I'll double-check this as a whole one more time tomorrow!

@chrisvanrun chrisvanrun self-assigned this Feb 10, 2026
…quest task on configure algorithm phases form (#4504)

Co-authored-by: Chris van Run <chrisvanrun@users.noreply.github.com>
@koopmant koopmant force-pushed the enable-more-phases-for-budget branch from ddc86a1 to 282fc9a Compare February 10, 2026 15:51
@koopmant
Copy link
Copy Markdown
Contributor Author

One test was duplicated because I hadn't rebased before merging #4504. I carefully backtracked, but that was the only difference. Stacked PRs and squashed merge commits are a total nightmare.

@chrisvanrun
Copy link
Copy Markdown
Member

Stacked PRs and squashed merge commits are a total nightmare.

Yes, maybe we should not squash them when the stacking is 'merged down' and only do a final squash at the final merge into main? @jmsmkn would it make sense to allow that?

Copy link
Copy Markdown
Member

@chrisvanrun chrisvanrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One final scan complete!

@koopmant koopmant merged commit d21bccf into main Feb 11, 2026
12 checks passed
@koopmant koopmant deleted the enable-more-phases-for-budget branch February 11, 2026 10:14
@jmsmkn
Copy link
Copy Markdown
Member

jmsmkn commented Feb 12, 2026

Stacked PRs and squashed merge commits are a total nightmare.

Yes, maybe we should not squash them when the stacking is 'merged down' and only do a final squash at the final merge into main? @jmsmkn would it make sense to allow that?

That would then allow non-squashed commits into main, so is a no-go. PRs should be made to main that are small and reviewable.

@koopmant
Copy link
Copy Markdown
Contributor Author

That would then allow non-squashed commits into main, so is a no-go.

Can we allow non-squashed merges if main is not the target branch?

PRs should be made to main that are small and reviewable.

Generally, I think this is the way to go. Stacked PR's are a slippery slope that lead to work that is hard to review. Just because it is split up, doesn't always make it easier to review. @chrisvanrun I think you'll agree?

@chrisvanrun
Copy link
Copy Markdown
Member

chrisvanrun commented Feb 12, 2026

Generally, I think this is the way to go. Stacked PR's are a slippery slope that lead to work that is hard to review. Just because it is split up, doesn't always make it easier to review. @chrisvanrun I think you'll agree?

Tricky. In this case it was all the same change (in essence) but it propagated to different parts of the code base. Any split would have broken main, so I think a feature branch was the obvious choice for creating smaller PRs.

Splitting a large PR into smaller PRs post hoc, like with this change set, always runs into problems with upstream changes and squashes. IMO - optimally you work up to a small change set that makes some sense as a whole, push it out in a PR for reviewing and then work on the next change set. And then make sure to never work on the next step after that, and consider to be blocked when the first PR is stuck in reviewing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants